package com.css.landslide.risk.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.config.QueueConfig;
import com.css.config.ThreadPoolConfig;
import com.css.influence.entity.MessageLog.service.MessageLogService;
import com.css.influence.entity.SettingSeismicInfluenceflied;
import com.css.landslide.risk.entity.GisInfluencelandslide;
import com.css.landslide.risk.entity.LandslideRisk;
import com.css.landslide.risk.entity.LandslideRiskLevel;
import com.css.landslide.risk.entity.LandslideRiskRaster;
import com.css.landslide.risk.mapper.InfluenceLandslideMapper;
import com.css.landslide.risk.mapper.LandslideRiskMapper;
import com.css.landslide.risk.mapper.LandslideRiskRasterMapper;
import com.css.landslide.risk.param.DatasourceBaseParam;
import com.css.landslide.risk.param.LandslideParam;
import com.css.landslide.risk.service.GisInfluencelandslideService;
import com.css.landslide.risk.service.LandslideRiskLevelService;
import com.css.landslide.risk.service.LandslideRiskService;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKTReader;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author dingling
 * @desc 滑坡危险性
 * @date 2024-09-26 16:19
 **/

@Slf4j
@Service
public class LandslideRiskServiceImpl extends ServiceImpl<LandslideRiskMapper, LandslideRisk> implements LandslideRiskService {

    /**
     *  e
    **/
    private static final double PARAM1 = 2.7182818284;

    private static final double PARAM2 = 0.00250165038535077;
    /**
     * ln2
    **/
    private static final double PARAM3 = 0.6931;


    @Resource
    private InfluenceLandslideMapper influenceLandslideMapper;

    @Autowired
    private LandslideRiskLevelService landslideRiskLevelService;

    @Autowired
    private GisInfluencelandslideService gisInfluencelandslideService;

    private static final Map<String, Integer> retryMap = new ConcurrentHashMap<>();
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MessageLogService messageLogService ;

    @Resource
    LandslideRiskRasterMapper landslideRiskRasterMapper;

    //失败重试次数
    @Value("${spring.rabbitmq.failedRetry}")
    private Integer failedRetry;


    @Override
    public List<SettingSeismicInfluenceflied> getInfluenceList(LandslideParam dsEntity) {
        try {
            DynamicDataSourceContextHolder.push(dsEntity.getDataSourceKey());
            QueryWrapper<SettingSeismicInfluenceflied> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("st_astext(geom) as geomText,geom,earth_quake_id, earthquake_level, dz_intensity, version");

            if (StringUtils.isNotBlank(dsEntity.getEarthQuakeId())){
                queryWrapper.eq("earth_quake_id",dsEntity.getEarthQuakeId());
            }
            if (StringUtils.isNotBlank(dsEntity.getInfluenceVersion())){
                queryWrapper.eq("version", dsEntity.getInfluenceVersion());
            }
            if (dsEntity.getDzIntensity() != null){
                queryWrapper.ge("dz_intensity::int", dsEntity.getDzIntensity());
            }
            queryWrapper.orderByDesc("dz_intensity");

            return influenceLandslideMapper.selectList(queryWrapper);
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    @Override
    public List<LandslideRisk> selectRiskLandslideProvince(DatasourceBaseParam dsEntity, String geom){
        try {
            DynamicDataSourceContextHolder.push(dsEntity.getDataSourceKey());
            return  this.getBaseMapper().selectRiskLandslide(geom);
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    public List<LandslideRiskRaster> selectRiskLandslideProvince1(DatasourceBaseParam dsEntity, String geom,int start,int end){
        String peek ;
        try {
            DynamicDataSourceContextHolder.push(dsEntity.getDataSourceKey());
            peek = DynamicDataSourceContextHolder.peek();
            return  landslideRiskRasterMapper.selectRiskLandslide(geom,start,end);
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    @Override
    public int selectCount(DatasourceBaseParam dsEntity){
        try {
            DynamicDataSourceContextHolder.push(dsEntity.getDataSourceKey());
            return  this.getBaseMapper().selectCount(new QueryWrapper<>());
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    public int selectCount1(DatasourceBaseParam dsEntity){
        try {
            DynamicDataSourceContextHolder.push(dsEntity.getDataSourceKey());
            return  landslideRiskRasterMapper.selectCount(new QueryWrapper<>());
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }
    public int selectCount2(DatasourceBaseParam dsEntity){
        try {
            DynamicDataSourceContextHolder.push("province_root");
            return  landslideRiskRasterMapper.selectCount(new QueryWrapper<>());
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    @Override
    public List<LandslideRisk> selectRiskLandslide(String geom){
        return this.getBaseMapper().selectRiskLandslide(geom);
    }

    // 初始化一个固定大小的线程池
    //private final ExecutorService executorService = Executors.newFixedThreadPool(5); // 10
    ThreadPoolExecutor executor = ThreadPoolConfig.exeBizThreadPoolExecutor;

    @RabbitListener(queues=QueueConfig.QUEUE_INFLUENCE_TO_LANDSLIDE, ackMode = "MANUAL")
    @Override
    public void calculateLandslideRisk(LandslideParam riskLevel, Channel channel, Message message) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    // 手动确认
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                    // 只查6级以上的
                    riskLevel.setDzIntensity(6);
                    doCalculateLandslideRisk(riskLevel);
                }catch (Exception e){
                    log.error("" + e);
                    String msgId = riskLevel.getEarthQuakeId();
                    int retryCount = retryMap.getOrDefault(msgId, 0);
                    log.error("{},--滑坡危险性评估||失败,处理消息时发生错误:{},即将开始第{}次消息重试...",msgId,e.getMessage(),retryCount + 1, e);
                    if (retryCount >= failedRetry - 1) {
                        log.error("{},---滑坡危险性评估||失败,消息将被拒绝，>>参数:{}",msgId,JSON.toJSONString(riskLevel));
                        // 拒绝消息，并且不重新入队
                        try {
                            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                        retryMap.remove(msgId);
                    } else {
                        // 重新发送消息到队列
                        try {
                            channel.basicPublish(message.getMessageProperties().getReceivedExchange(),
                                    message.getMessageProperties().getReceivedRoutingKey(),
                                    MessageProperties.MINIMAL_PERSISTENT_BASIC,
                                    JSON.toJSONBytes(riskLevel));
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                        retryMap.put(msgId, retryCount + 1);
                        log.error("地震id"+msgId+"-- 滑坡危险性评估"+"|| 失败。>> 参数:"+ JSON.toJSONString(riskLevel));
                    }
//                    try {
//                        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
//                    }catch (Exception e1){
//                        log.error("" + e1);
//                    }
                }
            }
        };
        // 将任务提交到线程池中执行
        executor.submit(runnable);
    }

    /**
     * 手动计算滑坡危险性
    **/
    @Override
    public String calculateLandslideRiskManual(LandslideParam riskLevel) {

        try {

            doCalculateLandslideRisk(riskLevel);

        }catch (Exception e){
            //
            log.error("" + e);
            return "滑坡危险性数据计算：出现未知异常";
        }
        return "";
    }


    @DSTransactional
    private void doCalculateLandslideRisk(LandslideParam riskLevel) {

        // 只查6级以上的
        riskLevel.setDzIntensity(6);

        log.info("开始计算{}数据源 {} 【地震滑坡次生灾害评估】",riskLevel.getDataSourceKey(), riskLevel.getEarthQuakeId());

        try {

            // 删除已有的
            landslideRiskLevelService.deleteProvince(riskLevel);

            if ("province_root".equals(riskLevel.getDataSourceKey())){
                gisInfluencelandslideService.deleteDs(riskLevel);
            }


            List<SettingSeismicInfluenceflied> influences = getInfluenceList(riskLevel);

            if (CollectionUtil.isEmpty(influences)){
                log.info("{} 影响场等级不足6，【地震滑坡次生灾害评估】结束！", riskLevel.getEarthQuakeId());
                return;
            }


            List<CompletableFuture<?>> futures = new ArrayList<>();
            List<LandslideRiskLevel> riskLevels = new ArrayList<>();

            for (int i = 0; i < influences.size(); i++) {

                SettingSeismicInfluenceflied influence = influences.get(i);
                //int finalI = i;
                CompletableFuture<?> future = CompletableFuture.runAsync(() -> {

                    // 先判断专用库有没有数据
                    List<LandslideRiskRaster> risks;
                    int count = selectCount1(riskLevel);
                    if (count > 0) { ;
                        for(int ii=1;ii<=count;ii+=5000){
                            int end = ii-1+5000;
                            risks = selectRiskLandslideProvince1(riskLevel, influence.getGeomText(), ii,end);
                            if (CollectionUtil.isEmpty(risks)) {
                                log.info("{}烈度{}无滑坡风险区域！", riskLevel.getEarthQuakeId(), influence.getDzIntensity());
                                // 统计不同烈度下 滑坡点个数  仅在国家库统计
                                if ("province_root".equals(riskLevel.getDataSourceKey())) {
                                    GisInfluencelandslide gisInfluencelandslide = new GisInfluencelandslide();
                                    gisInfluencelandslide.setId(IdUtil.simpleUUID());
                                    gisInfluencelandslide.setEarthquakeId(influence.getEarthQuakeId());
                                    gisInfluencelandslide.setLevel(influence.getDzIntensity());
                                    gisInfluencelandslide.setInfluenceVersion(influence.getVersion());
                                    gisInfluencelandslide.setGeom(influence.getGeom());
                                    gisInfluencelandslide.setNum("0");

                                    // 新增
                                    gisInfluencelandslideService.insertDs(riskLevel, gisInfluencelandslide);
                                }
                            }

                            if (CollectionUtil.isNotEmpty(risks)) {
                                for (LandslideRiskRaster record : risks) {
                                    LandslideRiskLevel landslideRiskLevel = calculateRisk1(influence,  record,riskLevel.getEarthQuakeId());
                                    riskLevels.add(landslideRiskLevel);
                                }
                                // 统计不同烈度下 滑坡点个数  仅在国家库统计
                                if ("province_root".equals(riskLevel.getDataSourceKey())) {
                                    GisInfluencelandslide gisInfluencelandslide = new GisInfluencelandslide();
                                    gisInfluencelandslide.setId(IdUtil.simpleUUID());
                                    gisInfluencelandslide.setEarthquakeId(influence.getEarthQuakeId());
                                    gisInfluencelandslide.setLevel(influence.getDzIntensity());
                                    gisInfluencelandslide.setInfluenceVersion(influence.getVersion());
                                    gisInfluencelandslide.setGeom(influence.getGeom());
                                    gisInfluencelandslide.setNum(String.valueOf(riskLevels.size()));
                                    gisInfluencelandslideService.insertDs(riskLevel, gisInfluencelandslide);
                                }
                            }
                        }

                    } else {
                        count = selectCount2(riskLevel);
                        if (count > 0) {
                            try{
                                DynamicDataSourceContextHolder.push("province_root");
                                for(int ii=1;ii<=count;ii+=5000){
                                    int end = ii-1+5000;
                                    String peek = DynamicDataSourceContextHolder.peek();
                                    if(StringUtils.isBlank(peek)){
                                        DynamicDataSourceContextHolder.push("province_root");
                                    }
                                    risks = landslideRiskRasterMapper.selectRiskLandslide(influence.getGeomText(), ii,end);
                                    if (CollectionUtil.isEmpty(risks)) {
                                        log.info("{}烈度{}无滑坡风险区域！", riskLevel.getEarthQuakeId(), influence.getDzIntensity());
                                        // 统计不同烈度下 滑坡点个数  仅在国家库统计
                                        if ("province_root".equals(riskLevel.getDataSourceKey())) {
                                            GisInfluencelandslide gisInfluencelandslide = new GisInfluencelandslide();
                                            gisInfluencelandslide.setId(IdUtil.simpleUUID());
                                            gisInfluencelandslide.setEarthquakeId(influence.getEarthQuakeId());
                                            gisInfluencelandslide.setLevel(influence.getDzIntensity());
                                            gisInfluencelandslide.setInfluenceVersion(influence.getVersion());
                                            gisInfluencelandslide.setGeom(influence.getGeom());
                                            gisInfluencelandslide.setNum("0");
                                            gisInfluencelandslideService.insertDs(riskLevel, gisInfluencelandslide);
                                        }
                                    }

                                    if (CollectionUtil.isNotEmpty(risks)) {
                                        for (LandslideRiskRaster record : risks) {
                                            LandslideRiskLevel landslideRiskLevel = calculateRisk1(influence,  record,riskLevel.getEarthQuakeId());
                                            riskLevels.add(landslideRiskLevel);
                                        }
                                        // 统计不同烈度下 滑坡点个数  仅在国家库统计
                                        if ("province_root".equals(riskLevel.getDataSourceKey())) {
                                            GisInfluencelandslide gisInfluencelandslide = new GisInfluencelandslide();
                                            gisInfluencelandslide.setId(IdUtil.simpleUUID());
                                            gisInfluencelandslide.setEarthquakeId(influence.getEarthQuakeId());
                                            gisInfluencelandslide.setLevel(influence.getDzIntensity());
                                            gisInfluencelandslide.setInfluenceVersion(influence.getVersion());
                                            gisInfluencelandslide.setGeom(influence.getGeom());
                                            gisInfluencelandslide.setNum(String.valueOf(riskLevels.size()));
                                            gisInfluencelandslideService.insertDs(riskLevel, gisInfluencelandslide);
                                        }
                                    }
                                }
                            }catch (Exception w){
                                w.printStackTrace();
                            }finally {
                                DynamicDataSourceContextHolder.clear();
                            }


                        }
                    }
                }, ThreadPoolConfig.exeBizThreadPoolExecutor);

                futures.add(future);
            }

            CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            allFutures.get();

            if (CollectionUtil.isNotEmpty(riskLevels)) {
                landslideRiskLevelService.batchInsert(riskLevel, riskLevels);
            }

        }catch (Exception e){
            log.error("" + e);
            throw new RuntimeException(e.getMessage());
        }


        log.info("计算 {}数据源 {}【地震滑坡次生灾害评估】结束！", riskLevel.getDataSourceKey(), riskLevel.getEarthQuakeId());
    }

    @DSTransactional
    private void doCalculateLandslideRiskBak(LandslideParam riskLevel) {

        // 只查6级以上的
        riskLevel.setDzIntensity(6);

        log.info("开始计算{}数据源 {} 【地震滑坡次生灾害评估】",riskLevel.getDataSourceKey(), riskLevel.getEarthQuakeId());

        try {

            // 删除已有的
            landslideRiskLevelService.deleteProvince(riskLevel);

            if ("province_root".equals(riskLevel.getDataSourceKey())){
                gisInfluencelandslideService.deleteDs(riskLevel);
            }


            List<SettingSeismicInfluenceflied> influences = getInfluenceList(riskLevel);

            if (CollectionUtil.isEmpty(influences)){
                log.info("{} 影响场等级不足6，【地震滑坡次生灾害评估】结束！", riskLevel.getEarthQuakeId());
                return;
            }


            List<CompletableFuture<?>> futures = new ArrayList<>();
            List<LandslideRiskLevel> riskLevels = new ArrayList<>();

            for (int i = 0; i < influences.size(); i++) {

                SettingSeismicInfluenceflied influence = influences.get(i);
                int finalI = i;


                CompletableFuture<?> future = CompletableFuture.runAsync(() -> {

                    // 先判断专用库有没有数据
                    List<LandslideRisk> risks;
                    if (selectCount(riskLevel) > 0) {
                        risks = selectRiskLandslideProvince(riskLevel, influence.getGeom());
                    } else {
                        risks = this.baseMapper.selectRiskLandslide(influence.getGeom());
                    }

                    if (CollectionUtil.isEmpty(risks)) {
                        log.info("{}烈度{}无滑坡风险区域！", riskLevel.getEarthQuakeId(), influence.getDzIntensity());

                        // 统计不同烈度下 滑坡点个数  仅在国家库统计
                        if ("province_root".equals(riskLevel.getDataSourceKey())) {
                            GisInfluencelandslide gisInfluencelandslide = new GisInfluencelandslide();
                            gisInfluencelandslide.setId(IdUtil.simpleUUID());
                            gisInfluencelandslide.setEarthquakeId(influence.getEarthQuakeId());
                            gisInfluencelandslide.setLevel(influence.getDzIntensity());
                            gisInfluencelandslide.setInfluenceVersion(influence.getVersion());
                            gisInfluencelandslide.setGeom(influence.getGeom());
                            gisInfluencelandslide.setNum("0");

                            // 新增
                            gisInfluencelandslideService.insertDs(riskLevel, gisInfluencelandslide);
                        }

                        return;
                    }

                    if (CollectionUtil.isNotEmpty(risks)) {
                        for (LandslideRisk record : risks) {
                            LandslideRiskLevel landslideRiskLevel = calculateRisk(influence,  record);
                            if (!BooleanUtil.isFalse(landslideRiskLevel.getHasRisk())) {
                                landslideRiskLevel.setId(IdUtil.simpleUUID());
                                landslideRiskLevel.setEarthQuakeId(riskLevel.getEarthQuakeId());
                                landslideRiskLevel.setDzVersion(influence.getVersion());
                                landslideRiskLevel.setDzIntensity(influence.getDzIntensity());
                                landslideRiskLevel.setCreateTime(new Date());
                                riskLevels.add(landslideRiskLevel);
                            }

                        }

                        // 统计不同烈度下 滑坡点个数  仅在国家库统计
                        if ("province_root".equals(riskLevel.getDataSourceKey())) {
                            GisInfluencelandslide gisInfluencelandslide = new GisInfluencelandslide();
                            gisInfluencelandslide.setId(IdUtil.simpleUUID());
                            gisInfluencelandslide.setEarthquakeId(influence.getEarthQuakeId());
                            gisInfluencelandslide.setLevel(influence.getDzIntensity());
                            gisInfluencelandslide.setInfluenceVersion(influence.getVersion());
                            gisInfluencelandslide.setGeom(influence.getGeom());
                            gisInfluencelandslide.setNum(String.valueOf(riskLevels.size()));

                            gisInfluencelandslideService.insertDs(riskLevel, gisInfluencelandslide);
                        }
                    }

                }, ThreadPoolConfig.exeBizThreadPoolExecutor);

                futures.add(future);
            }

            CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            allFutures.get();

            if (CollectionUtil.isNotEmpty(riskLevels)) {
                landslideRiskLevelService.batchInsert(riskLevel, riskLevels);
            }

        }catch (Exception e){
            log.error("" + e);
            throw new RuntimeException(e.getMessage());
        }


        log.info("计算 {}数据源 {}【地震滑坡次生灾害评估】结束！", riskLevel.getDataSourceKey(), riskLevel.getEarthQuakeId());
    }
    /**
     * 发送报告
    **/
    private void sendReport(Map<String,Object> toReportMap){

        // todo 发送
        if (true){
            return;
        }

        String status = "成功";

        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE, QueueConfig.KEY_INFLUENCE_TO_REPORT, toReportMap);
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE, QueueConfig.KEY_INFLUENCE_TO_REPORT, toReportMap);
                    flag = true;
                    break;
                }catch (Exception ignored){
                    // nothing
                }
            }
            if(!flag){
                status = "失败";
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(toReportMap), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_REPORT,status, content,"影响场发送消息给报告","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }

    /**
     * 危险等级
     * 1 低、2低、3中、4高、5极高
     *
    **/
    private Integer getRiskLevel(BigDecimal riskValue){

        int level;
        if (riskValue.compareTo(BigDecimal.valueOf(0.0001)) < 0){
            level = 1;
        }else if (riskValue.compareTo(BigDecimal.valueOf(0.001)) < 0){
            level = 2;
        }else if (riskValue.compareTo(BigDecimal.valueOf(0.01)) < 0){
            level = 3;
        }else if (riskValue.compareTo(BigDecimal.valueOf(0.1)) < 0){
            level = 4;
        }else{
            level = 5;
        }

        return level;

    }

    @Override
    public LandslideRiskLevel calculateRisk(List<SettingSeismicInfluenceflied> influences, LandslideRisk landslide) {
        BigDecimal level = BigDecimal.valueOf(0);

        LandslideRiskLevel riskLevel = new LandslideRiskLevel();

        BigDecimal l;
        for (SettingSeismicInfluenceflied influence : influences) {

            // 与多个场相交的话 得取最大的那个
            l = doCalculateRisk(influence, landslide);

            if (l.compareTo(level) > 0 ){
                level = l;
                riskLevel.setRiskValue(level);
                riskLevel.setDzVersion(influence.getVersion());
                riskLevel.setDzIntensity(influence.getDzIntensity());
            }
        }
        return riskLevel;
    }


    /**
     * 如果不确定 是否相交的可以走这个
     *
    **/
    @Override
    public BigDecimal doCalculateRisk(SettingSeismicInfluenceflied influence,  LandslideRisk landslide) {

        WKTReader reader = new WKTReader();
        Geometry geometry;
        Geometry geometry2;

        double l = 0;

        try {
            geometry = reader.read(influence.getGeomText());

            geometry2 = reader.read(landslide.getGeomText());

            // shortest  border distance
            double distance = geometry.distance(geometry2);

            // 在影响场内
            if (distance <=  0){
                l = 1 / (1 + Math.pow(PARAM1, (0 - PARAM2 * Math.pow(PARAM1, PARAM3 *
                        Integer.parseInt(influence.getDzIntensity())) - landslide.getValue())));
            }
        }catch (Exception e){
            log.error("计算危险等级失败；" + e);
        }

        return BigDecimal.valueOf(l);
    }

    private LandslideRiskLevel calculateRisk1(SettingSeismicInfluenceflied influence, LandslideRiskRaster landslide,String earthQuakeId) {
        LandslideRiskLevel riskLevel = new LandslideRiskLevel();
        /**
         * 说明：intensity.tif是影响场图层，数值就是VI度就是6，VII度就是7，VIII度就是8等等。
         * 		其中data.tif为数据管理模块维护的专用数据【地震滑坡危险性数据】。  栅格数据
         * 		建议选取0.0001，0.001，0.01，0.1为间断点，分为极低、低、中、高、极高这样的分类。
         * 		保存极低、低、中、高、极高结果，作为“快速评估滑坡危险性分布图”数据。
         */
        double l = 0;
        try{
            l = 1 / (1 + Math.pow(PARAM1, (0 - PARAM2 * Math.pow(PARAM1, PARAM3 *
                    Integer.parseInt(influence.getDzIntensity())) - landslide.getValue())));
        }catch (Exception e){
            e.printStackTrace();
        }
        BigDecimal level = BigDecimal.valueOf(l);
        riskLevel.setGeom(landslide.getIntersectGeom());
        Integer levelValue = getRiskLevel(level);
        riskLevel.setRiskValue(level);
        riskLevel.setDzVersion(influence.getVersion());
        riskLevel.setDzIntensity(influence.getDzIntensity());
        riskLevel.setRiskLevel(levelValue);
        riskLevel.setId(IdUtil.simpleUUID());
        riskLevel.setEarthQuakeId(earthQuakeId);
        riskLevel.setCreateTime(new Date());
        return riskLevel;
    }

    private LandslideRiskLevel calculateRisk(SettingSeismicInfluenceflied influence, LandslideRisk landslide) {
        LandslideRiskLevel riskLevel = new LandslideRiskLevel();
        /**
         * 说明：intensity.tif是影响场图层，数值就是VI度就是6，VII度就是7，VIII度就是8等等。
         * 		其中data.tif为数据管理模块维护的专用数据【地震滑坡危险性数据】。  栅格数据
         * 		建议选取0.0001，0.001，0.01，0.1为间断点，分为极低、低、中、高、极高这样的分类。
         * 		保存极低、低、中、高、极高结果，作为“快速评估滑坡危险性分布图”数据。
         */
        double l = 1 / (1 + Math.pow(PARAM1, (0 - PARAM2 * Math.pow(PARAM1, PARAM3 *
                Integer.parseInt(influence.getDzIntensity())) - landslide.getValue())));
        BigDecimal level = BigDecimal.valueOf(l);
        riskLevel.setGeom(landslide.getIntersectGeom());
        Integer levelValue = getRiskLevel(level);
        riskLevel.setRiskValue(level);
        riskLevel.setDzVersion(influence.getVersion());
        riskLevel.setDzIntensity(influence.getDzIntensity());
        riskLevel.setRiskLevel(levelValue);
        riskLevel.setId(IdUtil.simpleUUID());
        riskLevel.setEarthQuakeId(riskLevel.getEarthQuakeId());
        riskLevel.setCreateTime(new Date());
        return riskLevel;
    }

    public LandslideRiskLevel calculateRiskBak(List<SettingSeismicInfluenceflied> influences, Integer i, LandslideRisk landslide) {

        LandslideRiskLevel riskLevel = new LandslideRiskLevel();

        SettingSeismicInfluenceflied influence = influences.get(i);

        // 与多个场相交的话 得取最大的那个
        BigDecimal level = doCalculateRisk(influence, landslide);
        riskLevel.setGeom(landslide.getIntersectGeom());
        riskLevel.setHasRisk(true);

        if (i > 0){
            try {
                SettingSeismicInfluenceflied influenceHigher = influences.get(i - 1);

                WKTReader reader = new WKTReader();
                Geometry geometry;
                Geometry geometry2;


                geometry = reader.read(landslide.getIntersectGeomText());

                geometry2 = reader.read(influenceHigher.getGeomText());

                // a difference from b
                // symDifference is difference  a and b
                Geometry difference = geometry.difference(geometry2);

                if (difference.isEmpty()){
                    riskLevel.setHasRisk(false);
                }

                riskLevel.setGeom(difference.toString());


            }catch (Exception e){
                log.error("计算相交失败：" + e);
            }

        }

        Integer levelValue = getRiskLevel(level);

        riskLevel.setRiskValue(level);
        riskLevel.setDzVersion(influence.getVersion());
        riskLevel.setDzIntensity(influence.getDzIntensity());
        riskLevel.setRiskLevel(levelValue);

        return riskLevel;
    }

}
